#include "types.h"
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "proc.h"
#include "spinlock.h"
#include "sched.h"
#include "rq.h"
#include "sched_stride.h"
#include "sched_stride_tree.h"
#define SCHED_STRIDE
int
sys_fork(void)
{
  int pid;
  struct proc *np;

  if((np = copyproc(cp)) == 0){
    cprintf("sysfork failed here\n");
    return -1;
  }
  acquire(&(cpus[cpu()].rq->rq_lock));
  pid = np->pid;
  np->state = RUNNABLE;
  enqueue_proc(cpus[cpu()].rq, np);
  release(&(cpus[cpu()].rq->rq_lock));
  return pid;
}

int
sys_exit(void)
{
  exit();
  return 0;  // not reached
}

int
sys_wait(void)
{
  return wait();
}

int
sys_kill(void)
{
  int pid;

  if(argint(0, &pid) < 0)
    return -1;
  return kill(pid);
}

int
sys_getpid(void)
{
//  cprintf("sys_getpid: [%s]\n", cp->name);
  return cp->pid;
}

int
sys_sbrk(void)
{
  int addr;
  int n;

  if(argint(0, &n) < 0)
    return -1;
  if((addr = growproc(n)) < 0)
    return -1;
  return addr;
}

int
sys_sleep(void)
{
  int n, ticks0;
  
  if(argint(0, &n) < 0)
    return -1;
  acquire(&tickslock);
  ticks0 = ticks;
  while(ticks - ticks0 < n){
    if(cp->killed){
      release(&tickslock);
      return -1;
    }
    sleep(&ticks, &tickslock);
  }
  release(&tickslock);
  return 0;
}
int 
sys_tick(void)
{
	int now;
	acquire(&tickslock);
	now = ticks;
	release(&tickslock);
	return now;
}
#ifdef SCHED_STRIDE
int
sys_ticket(void)
{
	//acquire(&(cpus[cpu()].rq->rq_lock));
	int pid;
	int ticket;
	int old_ticket;
    if(argint(0, &pid) < 0)
        return -1;
	if(argint(1, &ticket) < 0)
		return -1;
	if(cp->pid == pid){
		old_ticket = cp->ticket;
		cp->ticket = ticket;
		cp->stride = sched_class_stride.stride1 / cp->ticket;
		global_ticket_update(cpus[cpu()].rq, ticket - old_ticket);
		yield();
		return 1;
	}
	else{
		struct rq_node *node;
		acquire(&(cpus[cpu()].rq->rq_lock));
		node = cpus[cpu()].rq->head;
		while(node != NULL && node->proc->pid != pid){
			node = node->next;
		}
		if(node == NULL){
			cprintf("proc with this pid not found!\n");
			return -1;
		}
		old_ticket = node->proc->ticket;
		node->proc->ticket = ticket;
		node->proc->stride = sched_class_stride.stride1 / node->proc->ticket;
		node->proc->remain = node->proc->remain * old_ticket / ticket;
		queue_flesh(cpus[cpu()].rq, node->proc);
		release(&(cpus[cpu()].rq->rq_lock));
		return 1;
	}
	
}
#endif

#ifdef SCHED_STRIDE_TREE
int
sys_ticket(void)
{
	//acquire(&(cpus[cpu()].rq->rq_lock));
	int pid;
	int ticket;
	int old_ticket;
    if(argint(0, &pid) < 0)
        return -1;
	if(argint(1, &ticket) < 0)
		return -1;
	if(cp->pid == pid){
		node_modify(cp->rq, cp->rq_node, ticket-cp->ticket);
		yield();
		return 1;
	}
	else{
		panic("sys_call_ticket");
		return -1;
	}
	
}
#endif

int sys_response(void)
{
	int i;
	for(i=1;i<1000;i++){
		if(response[i]!=0)
		cprintf("responsetick=%d times=%d \n ", i, response[i]);
	}
	i++;
}